﻿// -----------------------------
// Copyright © Kodi Studios 2012
// -----------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;

namespace Kodi.Picturethrill
{
    class CacheService
    {
        #region Private Fields
        private string imageCacheFolder;

        private Dictionary<string, string> imageCacheHash = new Dictionary<string, string>();

        private const string CachedImagesNodeName = "CachedImages";
        private const string CachedImageNodeName = "CachedImage";
        private const string ProviderNameNodeName = "ProviderName";
        #endregion

        public void Cache(string providerName, string fileName)
        {
            string cachedFileName = Path.Combine(imageCacheFolder, Path.GetFileName(fileName));
            try
            {
                File.Copy(fileName, cachedFileName, overwrite: true);
            }
            catch (IOException e)
            {
                Log.Comment("Cache File Copy " + fileName + " " + cachedFileName + "\nException: " + e.ToString());
            }
            imageCacheHash[providerName] = cachedFileName;
        }

        public string GetCached(string providerName)
        {
            if (this.imageCacheHash.ContainsKey(providerName))
            {
                string cachedFileName = this.imageCacheHash[providerName];
                if (File.Exists(cachedFileName))
                {
                    return cachedFileName;
                }
            }

            return string.Empty;
        }

        public void Load(string configFile, string imageCacheFolderInit)
        {
            this.imageCacheFolder = imageCacheFolderInit;

            if (File.Exists(configFile))
            {
                // Load file
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(configFile);

                XmlNode node = xmlDocument.SelectSingleNode(CachedImagesNodeName);

                this.imageCacheHash.Clear();

                foreach (XmlElement cachedImageNode in node.SelectNodes(CachedImageNodeName))
                {
                    string providerName = cachedImageNode.GetAttribute(ProviderNameNodeName);
                    string cachedImage = cachedImageNode.InnerText;
                    this.imageCacheHash[providerName] = cachedImage;
                }
            }
        }

        /// <summary>
        /// Saves file that points to Cached images.
        /// </summary>
        /// <param name="configFile">File to save configuration to.</param>
        public void Save(string configFile)
        {
            using (Log.Group())
            {
                XmlDocument xmlDocument = new XmlDocument();
                XmlElement node = xmlDocument.CreateElement(CachedImagesNodeName);
                xmlDocument.AppendChild(node);

                foreach (string providerName in this.imageCacheHash.Keys)
                {
                    XmlElement cachedImageNode = node.OwnerDocument.CreateElement(CachedImageNodeName);
                    cachedImageNode.SetAttribute(ProviderNameNodeName, providerName);
                    cachedImageNode.InnerText = this.imageCacheHash[providerName];
                    node.AppendChild(cachedImageNode);
                }

                xmlDocument.Save(configFile);
                Log.Comment("Cache saved to: " + configFile);
            }
        }

        internal void RemoveNonCached()
        {
            using (Log.Group())
            {
                HashSet<string> knownFileNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

                // Go through known cache files
                foreach (string fileName in this.imageCacheHash.Values)
                {
                    if (!knownFileNames.Contains(fileName))
                    {
                        knownFileNames.Add(fileName);
                    }
                }

                // Remove all other files from cached folder
                if (Directory.Exists(this.imageCacheFolder))
                {
                    DirectoryInfo directoryInfo = new DirectoryInfo(this.imageCacheFolder);
                    foreach (FileInfo fileName in directoryInfo.GetFiles())
                    {
                        if (!knownFileNames.Contains(fileName.FullName))
                        {
                            Log.Comment("Deleting file: " + fileName.FullName);
                            fileName.Delete();
                        }
                    }
                }
            }
        }
    }
}
